/***************************************************************************//**
 * @file mac_transmitter.c
 * @brief for mac active transfer data, include LBT,retry,TDMA.
 * @author ze .
 * @date  2022/7/03.
 * @copyright Copyright 
 ******************************************************************************/
#include "mac_transmitter.h"
#include "mac_TDMA.h"
#include "mac_packetHandle.h"
#include "mac_receiver.h"
#include "mac_fhss.h"
#include "em_core.h"
#include "mac_timeSync.h"
#include "device_type.h"
#include "device.h" //用于get自身或系统内外设的相关信息

//#define LBT_TX_WRITE_FIFO_FIRST

#define CHECK_RF_TX_IDLE (EN_MAC_RF_STATE_IDLE == getRfState() || EN_MAC_RF_STATE_WAIT_PREAMBLE == getRfState()) //ToDo 可直接读取芯片状态，IO脚/寄存器，为快速反应，半双工芯片 TXIDLE即为芯片IDLE

#define TRANS_EVENT_LBT_NOT_NEED_BITMASK     ((uint32_t) (GET_DW_BIT_MASK(EN_TRANS_REQ_SYNC_BCAST) | GET_DW_BIT_MASK(EN_TRANS_REQ_ADHOC_SPVN_ACK) | GET_DW_BIT_MASK(EN_TRANS_REQ_FILE_DATA_TX)) )
#define TRANS_EVENT_LBT_NEEDED_BITMASK       (~TRANS_EVENT_LBT_NOT_NEED_BITMASK)

#define MAC_TX_STATEMACHINE_HARD_TIMER  EN_LP_HARD_TIMER_EM3_SYS_RTC
typedef struct 
{   
    //uint8_t byEventType;
    uint8_t byLbtCount;
    uint8_t byLbtMaxTimes;
}LBT_CTRL_ST;

typedef struct 
{    
    TRANS_REQ_E enHandlingEventType;//状态机正在处理的事件类型
    uint8_t*  pPacketToSend;        //待发送报文指针
    RETRY_CTRL_ST stRegisterCtrl; //注册请求重传控制
    RETRY_CTRL_ST stRetryUpCtrl;//上行重传控制,为CHECK_TRANS_EVENT_TYPE_IS_ACTIVE_UPLINK
    RETRY_CTRL_ST sRetryDownCtrl[DOWNLINK_CONCURRENCY_CAPABILITY];//作为HUB/Expander下行重传控制，具有向多目的地发起adhoc点对点的能力，添加不同目的地的点对点adhoc任务，暂定5个CHECK_TRANS_EVENT_TYPE_IS_ACTIVE_DOWNLINK
    LBT_CTRL_ST  stLbtCtrl; //所有需要做LBT的发送任务共用该控制块
    PFUNC_TX_CALLBACK ppMacCallbackTx[EN_TRANS_REQ_MAX];//在发送的各个状态回调
}TX_STATE_CTRL_BLOCK_ST;

/************************************属性变量定义************************************************************************/

//状态机内控制块
static TX_STATE_CTRL_BLOCK_ST  s_stTxCtrlBlock;
//实例化 Tx状态机
static STATEM_STATE_MACHINE_ST s_instTxStateMachine ;
static volatile uint32_t  s_dwTransEventBitM = 0;//发送事件掩码，最大32个 EN_TRANS_REQ_MAX    
static volatile uint8_t  s_pTransEventDestId[EN_TRANS_REQ_MAX]; //每个发送事件的 目的地址，ToDo, 每个发送事件的信道如何获取，EN_TRANS_REQ_ADHOC_SPVN_ACK，EN_TRANS_REQ_FILE_DATA_TX信道独立，其他主信道   
static volatile uint32_t  s_dwMacTxEventTypeBitMask = 0;
static volatile uint32_t  s_dwMacTxEventValueBitMask = 0;

static volatile uint8_t    s_TxWaitAckChannel = 0;
static volatile uint8_t    s_RecvAckChannel = 0;

static uint16_t wTxPreambleLen = 0; //bit表示

static MultiTimer waitValidSlotTimer={.Handle = 0x00F0, .status = EN_MULTITIMER_STATUS_IDLE};// ToDo，在下文中使用transReqEventGuard()
static MultiTimer waitSendTimer ={.Handle = 0x00F1}; //若内存不够时，timer或复用 或减少结构体定义的长度
static MultiTimer waitAckTimer ={.Handle = 0x00F2};
static MultiTimer lbtTimer ={.Handle = 0x00F3}; // ToDo, 不再打断事件，而是允许LBTtimer运行，并加快lbt timer间隔. 事件非空时休眠!当 lbtTimer运行时，0819待增加timer异常的轮询机制！

//static MultiTimer retryTimer={.Handle =0x00E0}; 0x00E0 —— 0x00EF 在重传控制块内定义，为重传定时器实例
#ifdef RFM_DEVICE
const uint16_t lbtDelayTime[LBT_REDO_COUNT_MAX] =//使用质数，避免整除效应
{327*3,307*4,280*4,349*3,369*3, 321*5,300*3,331*5,362*4,393*5}; //可区分HUB及RFM低功耗设备，HUB可加快LBT频次，需考虑HUB的应答延时，最小的延时时间需增加 0928 ToDo ，0116 若分配相同心跳时间槽，可LBT退避20ms-40ms随机避开应答时刻
#else
const uint16_t lbtDelayTime[LBT_REDO_COUNT_MAX] =//使用质数，避免整除效应
{296*2,311*2,274*3,314*4,303*3, 227*3,253*4,271*3,243*4,268*5}; //可区分HUB及RFM低功耗设备，HUB可加快LBT频次，需考虑HUB的应答延时，最小的延时时间需增加 0928 ToDo
#endif

#define RETRY_TIMES_MIN_TRY_RESYNC  6

#ifdef RFM_DEVICE
const uint16_t retryDelayTime[ADHOC_RETRY_COUNT_MAX] = //不超过65535 即2s //使用质数，避免整除效应
// 1    2     3      4      5         6      // 7      8      9     10  //>6后使用备用信道 最后1次主信道传输等应答失败，即可100ms延时后，往备用信道发送； 现阶段由于应答延时较大，重传间隔需拉开；
{3200*2,3276*3,3100*4,3300*4,3400*5,3200*7, 3000*2,3310*5,3620*5,3930*7};
//{327*5,3276,3276*2,3276*4,3276*8,   327*5,3276*2,3276*4,3276*8,32768};
#else
const uint16_t retryDelayTime[ADHOC_RETRY_COUNT_MAX] = //不超过65535 即2s //使用质数，避免整除效应
// 1    2     3      4      5         6     // 7      8      9     10  //>6后使用备用信道 最后1次主信道传输等应答失败，即可100ms延时后，往备用信道发送； 现阶段由于应答延时较大，重传间隔需拉开；
{3276*1,3200*2,3300*2,3400*3,3500*2,3600*3, 3000,3310*2,3620*2,3930*3};
#endif

/*************************************函数声明待定义*********************************************************************/
void writeTxFifo(uint8_t* pData, bool isReset)
{
    uint16_t ret = bsp_rf_write_tx_fifo(pData,pData[0]+1,isReset);
    if(get_mac_printf_log())
      printf("WF %d\r\n",ret);
}
void startTx(uint8_t chan, uint8_t antIdx)
{
  uint8_t ret = 0xFF;

  if(0 == antIdx)
    ret= bsp_rf_start_tx(chan,RAIL_TX_OPTION_ALT_PREAMBLE_LEN | RAIL_TX_OPTION_ANTENNA0,NULL); //指定天线0 发送
  else if(1 == antIdx)
    ret= bsp_rf_start_tx(chan,RAIL_TX_OPTION_ALT_PREAMBLE_LEN | RAIL_TX_OPTION_ANTENNA1,NULL); //指定天线1 发送
  else
    ret= bsp_rf_start_tx(chan,RAIL_TX_OPTION_ALT_PREAMBLE_LEN ,NULL); //随机天线，同上次接收选择的天线

  //if(!getMacRxStateEventType(EN_MAC_RX_EVENT_TYPE_RF_PREAMBLE_DONE)) // 发送已打断接收过程，强制false, ToDo bug!! 无法打断接收过程，待解决，此处先进行LBT退避之
  setMacRxStateEvent(EN_MAC_RX_EVENT_TYPE_RF_PREAMBLE_DONE,false); //ToDo debug 告知接收状态机，接收过程被打断，置false.是否合法？需debug关注

  if(!getMacRxStateEventType(EN_MAC_RX_EVENT_TYPE_RF_PAYLOAD_DONE))
    setMacRxStateEvent(EN_MAC_RX_EVENT_TYPE_RF_PAYLOAD_DONE,false); //ToDo debug 若尚未产生接收完成事件，则告知接收状态机，接收过程被打断，置false
  //else
  //  printf(":)"); //上一次发送 置PayloadDone false，未被处理
  if(get_mac_printf_log())
    printf("TA %d,%d,%d\r\n",ret,chan,antIdx);
}

bool checkLbtRssiIsPass()//返回true表示通过
{
    //ToDo
    int16_t rssi = bsp_rf_get_raw_rssi(true);
    if(get_mac_printf_log())
      printf("L%d\r\n",rssi);
    if(rssi > LBT_THRESHOLD_RSSI)
    {
        return false;//rssi大于阈值即失败
    }
    return true; //debug
}

#if  defined(RFM_DEVICE) && (!defined(SPVN_DISABLE))
static uint8_t s_byAutoDeciTxPower = 140;//默认14dbm 范围0-200 对应0dbm - 20.0dbm，ToDo从NVM内恢复？

#define AUTO_ADJUST_RSSI_THRESHOLD_HIGH  64 //-64dbm,大于该值，降低发射功率-0.5dbm
#define AUTO_ADJUST_RSSI_THRESHOLD_LOW   52 //-76dbm,小于该值，提高发射功率+0.5dbm

#define AUTO_ADJUST_TXPOWER_MIN  100 //10dbm,约14mA电流
#define AUTO_ADJUST_TXPOWER_MAX  200 //20dbm，约86mA电流
//根据HUB回显的接收该子设备上报的信号强度，动态调整发射功率，以节省功耗和降低对外干扰，ToDo，则其他子设备的LBT效果会减弱
//其中rssi值为0 - 128，对应-128dbm - 0dbm
void txpowerAutoAdjust(uint8_t rssi)
{
  int currentTxPower =0;
  uint8_t temp8;
  getThisParam(ENbyQrfH2, &temp8);

  if(temp8 )
  {

  }

  currentTxPower= bsp_rf_get_tx_power_bdm();
  //printf("TP%d",currentTxPower);

  if(rssi > AUTO_ADJUST_RSSI_THRESHOLD_HIGH)//步进减少发射功率
  {
      if(s_byAutoDeciTxPower > AUTO_ADJUST_TXPOWER_MIN)//如果自动调节的功率小于
      {

      }
  }
  else if(rssi < AUTO_ADJUST_RSSI_THRESHOLD_LOW)//步进增加发射功率
  {
      if(s_byAutoDeciTxPower < AUTO_ADJUST_TXPOWER_MAX)
      {

      }
  }
}
#endif

/************************************函数定义*****************************************************************************/
void setMacTxStateEvent(uint8_t type, bool isPass)
{
    if(type == EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE && isPass)//收到应答报文，进行时间同步
    {
        timeSyncToHub();
        #if defined(RFM_DEVICE) && (!defined(SPVN_DISABLE))
        txpowerAutoAdjust(getLastRecvPacketPoint()->start_of_packet[16]);//应答报文中的 第16字节表示RSSI
        #endif
    }

    CORE_DECLARE_IRQ_STATE;
    CORE_ENTER_CRITICAL();        
    s_dwMacTxEventTypeBitMask |= GET_DW_BIT_MASK(type);
    if(isPass)
    {
        s_dwMacTxEventValueBitMask |= GET_DW_BIT_MASK(type);
    }
    else
    {
        s_dwMacTxEventValueBitMask &= ~GET_DW_BIT_MASK(type);
    }
    CORE_EXIT_CRITICAL();        
}

static void clearMacTxStateEventType(MAC_TX_EVENT_TYPE_E type)
{
    CORE_DECLARE_IRQ_STATE;
    CORE_ENTER_CRITICAL();  
    s_dwMacTxEventTypeBitMask &= ~GET_DW_BIT_MASK(type);
    CORE_EXIT_CRITICAL(); 
}

static bool getMacTxStateEventType(uint8_t type)
{
    if(s_dwMacTxEventTypeBitMask & GET_DW_BIT_MASK(type))
    {
        return true;
    }
    return false;
}

static uint8_t getMacTxStateEventValue(uint8_t type)
{
    if(s_dwMacTxEventValueBitMask & GET_DW_BIT_MASK(type))
    {
        return 1;
    }
    return 0; 
}
//改造成bool或u8 结构体访问 ，就不用再临界保护之
static void setTransEventBitMask(TRANS_REQ_E type)
{
    CORE_DECLARE_IRQ_STATE;
    CORE_ENTER_CRITICAL(); 
    s_dwTransEventBitM |= GET_DW_BIT_MASK(type);
    CORE_EXIT_CRITICAL(); 
}

static void clearTransEventBitMask(uint32_t data)
{
    CORE_DECLARE_IRQ_STATE;
    CORE_ENTER_CRITICAL();      
    s_dwTransEventBitM &= (~data);
    CORE_EXIT_CRITICAL();     
}

static void clearTransEventType(TRANS_REQ_E type)
{
  CORE_DECLARE_IRQ_STATE;
  CORE_ENTER_CRITICAL();
  s_dwTransEventBitM &= ~(GET_DW_BIT_MASK(type));
  CORE_EXIT_CRITICAL();
}

uint32_t getMacTransEventBitMask()
{
    return s_dwTransEventBitM;
}

// 等待空闲时间槽超时，回调之，主要目的是唤醒设备
static void waitValidSlotTimerCallback(struct MultiTimerHandle* timeHandle,void* pData)
{
  //
}

//ToDo评估 TimerCallback在中断被调用的风险setMacTransEvent，需确保线程安全性
static void lbtTimerCallback(struct MultiTimerHandle* timeHandle,void* pData)
{
    uint8_t byData = (uint8_t)pData;
    int ret;
    ret = setMacTransEvent(byData,0xFF,0,0);
    if(ret < 0)
    {
        printf("LST%d-%d",byData,ret);
    }
}
//需确保线程安全性
static void retryTimerCallback(struct MultiTimerHandle* timeHandle,void* pData)
{
    uint8_t byData = (uint8_t)pData;
    int ret;
    ret = setMacTransEvent(byData,0xFF,0,LBT_REDO_COUNT_MAX);
    if(ret < 0)
    {
        printf("RST%d-%d",byData,ret);
    }
}    
//需确保线程安全性，ToDo 发送超时后需将RF置为非TX态
static void waitSendTimerCallback(struct MultiTimerHandle* timeHandle,void* pData)
{
    if(!getMacTxStateEventType(EN_MAC_TX_EVENT_TYPE_SEND_DONE))
      setMacTxStateEvent(EN_MAC_TX_EVENT_TYPE_SEND_DONE,false);
    else
      printf("+{");
    //置状态Idle，发送超时异常处理 ToDo
    bsp_set_rf_idle(RAIL_IDLE_ABORT, false);
    //清TXFIFO
    bsp_rf_reset_fifo(1,0);
    bsp_set_rf_idle(RAIL_IDLE_ABORT, false);
    printf("ESTO");//错误，RAIL RF失败
}    
//需确保线程安全性
static void waitAckTimerCallback(struct MultiTimerHandle* timeHandle,void* pData)
{
    if(!getMacTxStateEventType(EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE))
      setMacTxStateEvent(EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE,false); //超时留足够余量，此处不处理问题不大
    else
      printf("-}");
    //printf("[ERROR]wait ack timeout\r\n");
}   


/**
 * @brief 注册对应TRANS_REQ_E的TX回调函数
 * 
 * @param pFun 相应的transReq枚举请求事件回调设置，Todo
 * @return void
 */
void macTxCallbackSet(TRANS_REQ_E type, PFUNC_TX_CALLBACK pFun)
{
    if(type >= EN_TRANS_REQ_MAX)
    {
        return;
    }
    s_stTxCtrlBlock.ppMacCallbackTx[type] = pFun;
}

RETRY_CTRL_ST* getRetryCtrlBlock(TX_STATE_CTRL_BLOCK_ST* pstFsmData,TRANS_REQ_E type)
{
    uint8_t temp8;
    RETRY_CTRL_ST*  pstRetryCtrl = NULL;
    if(CHECK_TRANS_EVENT_TYPE_IS_ACTIVE_UPLINK(type))
    {
        pstRetryCtrl = &(pstFsmData->stRetryUpCtrl);
    }
    else if(type == EN_TRANS_REQ_REGISTER)
    {
        pstRetryCtrl = &(pstFsmData->stRegisterCtrl);
    }
    else if(CHECK_TRANS_EVENT_TYPE_IS_ACTIVE_DOWNLINK(type))
    {
        temp8 = type - EN_TRANS_REQ_ADHOC_DOWNLINK_START;
        pstRetryCtrl = &(pstFsmData->sRetryDownCtrl[temp8]);
    }
    return pstRetryCtrl;
}

int checkMacTransEvent(TRANS_REQ_E type)// 该函数的线程安全性，同时被timercallback任务/线程 及 其他应用程序调用；
{
    RETRY_CTRL_ST*  pstRetryCtrl = NULL;
    if(type >= EN_TRANS_REQ_MAX)
    {
        return -1;
    }
    //重复事件过滤，该事件bit位已存在
    if(getMacTransEventBitMask() & GET_DW_BIT_MASK(type))
    {
        //printf("[ERROR] Check transReq%d, already exist, Now mask0x%lx\r\n",type,getMacTransEventBitMask());
        return -2;
    }

    pstRetryCtrl = getRetryCtrlBlock(&s_stTxCtrlBlock,type);
    if(pstRetryCtrl != NULL )//需重传事件，在mac或app层置位，为首次
    {
        if(pstRetryCtrl->byRetryMaxTimes != 0)//该retryCrtl重传控制位置已存在事件，非空；
        {
            //spvn和adhoc互斥优先级，当adhoc进来时，若正在spvn强制打断，ToDo处理释放retry重传定时器
            if(CHECK_TRANS_EVENT_TYPE_IS_ACTIVE_UPLINK(type) && (EN_TRANS_REQ_SPVN == pstRetryCtrl->byEventType /*|| EN_TRANS_REQ_NONE == pstRetryCtrl->byEventType*/))
            {
                //printf("[DBG] SPVN will be interrupted by eventType%d\r\n",type);
            }
            else
            {
                //printf("[ERROR] Check Active transEvent type%d already existed:id%d,retry%d-%d! Now mask0x%lx\r\n",type,s_pTransEventDestId[type]
                //    ,pstRetryCtrl->byRetryCount,pstRetryCtrl->byRetryMaxTimes,getMacTransEventBitMask());
                return -3;
            }
        }
    }
    return 0;
}

void setTxAckChannel(uint8_t ackCh)
{
  s_RecvAckChannel = ackCh;
}
//非线程安全，尽量不应再中断内调用，特别是打断操作，即Adhoc不能在中断内调用。
//bug0911 未修复，在收到应答时，调用set心跳事件，不会返回错误，而且心跳发送事件标志可置位，但会将retryMaxTime = 0，导致重传时retryMax为0 //Add 0928若打断其他事件后会立刻产一次其他事件失败回调！，注意尽量不要在中断内执行该函数！
int setMacTransEvent(TRANS_REQ_E type,uint8_t destId,uint8_t retryMax,uint8_t lbtMax)// 该函数的线程安全性，同时被timercallback任务/线程 及 其他应用程序调用；
{
    RETRY_CTRL_ST*  pstRetryCtrl = NULL;

    if(type >= EN_TRANS_REQ_MAX)
    {
        return -1;
    }

    if(type == EN_TRANS_REQ_ADHOC_SPVN_ACK)//若需应答，则评估上次接收报文的时间同步误差
    {
        calcRfmTimeSyncError();
    }

    //重复事件过滤，该事件bit位已存在
    if(getMacTransEventBitMask() & GET_DW_BIT_MASK(type))
    {
        printf("ET%d-%d-0x%lx",type,destId,getMacTransEventBitMask());
        return -2;
    }
    
    pstRetryCtrl = getRetryCtrlBlock(&s_stTxCtrlBlock,type);
    if(retryMax != 0 && pstRetryCtrl != NULL )//需重传事件，在mac或app层置位，为首次
    {
        if(pstRetryCtrl->byRetryMaxTimes != 0)//该retryCrtl重传控制位置已存在事件，非空；
        {
            //spvn和adhoc互斥优先级，当adhoc进来时，若正在spvn强制打断，ToDo处理释放retry重传定时器,原来SPVN可打断SPVN，现在仅允许Adhoc打断Spvn
            if((EN_TRANS_REQ_ADHOC_UPLINK == type) && (EN_TRANS_REQ_SPVN == pstRetryCtrl->byEventType /*|| EN_TRANS_REQ_NONE == pstRetryCtrl->byEventType*/))
            {
                if(pstRetryCtrl->stRetryTimer.status != EN_MULTITIMER_STATUS_IDLE)//Add 0928 增加打断当前正在执行事件的代码，打断后并回调失败，允许下一个事件执行。ToDo 考虑将打断动作的范围扩展至全局！,将非线程安全！
                {
                    softwareMultiTimerStop(MAC_TX_STATEMACHINE_HARD_TIMER,&(pstRetryCtrl->stRetryTimer),0);
                    if(s_stTxCtrlBlock.ppMacCallbackTx[EN_TRANS_REQ_SPVN] != NULL)
                    {
                        s_stTxCtrlBlock.ppMacCallbackTx[EN_TRANS_REQ_SPVN] (&(s_stTxCtrlBlock.pPacketToSend), EN_MAC_TX_STATE_FAILED, pstRetryCtrl);//打断重传定时器，并失败回调
                    }
                    printf("RTINT");//需产生一次失败的回调，当状态机空闲的时候？Add0928
                }
                clearTransEventType(EN_TRANS_REQ_SPVN);//To Debug，clear spvn ,bug fixed 0818, 与 clearMacTxStateEvent函数名相近错误，未完全停止定时器，导致互相打断，重传事件定时器开启 形参改成retry-event

                printf("SIT");//Bug 0928 其中，Lbt定时器可能会再次置位心跳事件，导致异常发生
            }
            else
            {
                printf("E%d-%d,%d-%d 0x%lx",type,s_pTransEventDestId[type]
                    ,pstRetryCtrl->byRetryCount,pstRetryCtrl->byRetryMaxTimes,getMacTransEventBitMask());
                return -3;   
            }
        }

        s_pTransEventDestId[type] = destId; //首次赋值destId
    }
    else//无需重传 或需重传事件(pstRetryCtrl != NULL)由重传、LBT定时器回调置位，判断retryCrtl重传控制中该事件位置 是否为空
    {
        if((pstRetryCtrl != NULL) && (pstRetryCtrl->byRetryMaxTimes == 0 || type != pstRetryCtrl->byEventType))//重传设置的该retryCrtl重传控制位 当为空或被其他id占用时错误，或已被提前终止，需考虑回调事件失败？BUG240301新增 若已被其他类型占用，也失败赋值，避免心跳LBT或RETRY回调打断adhoc事件
        {
            printf("RE%d-%d:id%d,%d-%d-%d!%u",type,destId,s_pTransEventDestId[type]
                ,pstRetryCtrl->byEventType,pstRetryCtrl->byRetryCount,pstRetryCtrl->byRetryMaxTimes,getMacTransEventBitMask());
            return -4;
        }
        else if(pstRetryCtrl == NULL) //无需重传事件
        {
            s_pTransEventDestId[type] = destId; //首次赋值destId
        }
    }  

    if(type == EN_TRANS_REQ_ADHOC_SPVN_ACK)//ToDo，需在接收到主动上报报文后立即应答，强需求！ 应答报文，获取上次接收的报文的指针 add 0814，即在接收报文的时刻应答
    {
        setTxAckChannel(getLastRecvPacketPoint()->details.channel);
    }

    setTransEventBitMask(type);//使能相应事件

    //表示添加set主动上报需重传事件，且是首次添加，初始化相应的重传控制块，有缓存，故可直接更新
    if(retryMax != 0 && pstRetryCtrl != NULL)
    {
        pstRetryCtrl->byRetryMaxTimes = retryMax;
        pstRetryCtrl->byEventType = type; //降低新的adhoc事件压入时被 中断内新的spvn事件压入打断的概率
        pstRetryCtrl->byRetryCount = 0;
    }

    //针对需要LBT的报文，Lbt控制块更新，允许LBT被打断，无缓存仅最大次数均更新之。。打断前需立即回调lbtTimerCallback，以恢复该请求事件,见 transReqGuard
    if(!CHECK_TRANS_EVENT_TYPE_IS_LBT_NOT_NEED(type))
    {
      if(lbtMax != 0 )
      {
        s_stTxCtrlBlock.stLbtCtrl.byLbtMaxTimes = lbtMax;
        //lbt首次
        if(pstRetryCtrl != NULL)
        {
            pstRetryCtrl->byCrtlFlag &= ~RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED;
        }
      }
      else if(lbtMax == 0)
      {
        //lbt第2、3、4次
        if(pstRetryCtrl != NULL)
        {
            pstRetryCtrl->byCrtlFlag |= RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED;
        }
      }
    }

    return 0;
}


//pEvent出参,若有事件则赋值， true 表示有事件待处理，需阻止休眠，ToDo该函数用作休眠判断函数块内，休眠函数块前后需临界保护之
bool macTxStateMachineEventCheck(STATEM_TYPE_ST* pEvent)
{
    if(pEvent == NULL)
    {
        return false;
    }

    pEvent->type = EN_MAC_TX_EVENT_TYPE_NONE;
    switch(s_instTxStateMachine.currentState->handle)
    {
        case EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE:
          //如果存在 需要避开时隙的需LBT的上报事件，将不产生请求事件并允许休眠，同时，高优先级无需LBT的事件依然可立即执行
            if(getMacTransEventBitMask() && ( waitValidSlotTimer.status == EN_MULTITIMER_STATUS_IDLE || (getMacTransEventBitMask() & TRANS_EVENT_LBT_NOT_NEED_BITMASK) ) )
            {
                pEvent->type = EN_MAC_TX_EVENT_TYPE_TRANS_REQ;
            }
            break;    
        case EN_MAC_TX_STATE_LBT_CHECK:
            if(getMacTxStateEventType(EN_MAC_TX_EVENT_TYPE_LBT_CHECK_DONE))
            {
                pEvent->type = EN_MAC_TX_EVENT_TYPE_LBT_CHECK_DONE;
            }
            break;    
        case EN_MAC_TX_STATE_SEND:
            if(getMacTxStateEventType(EN_MAC_TX_EVENT_TYPE_SEND_DONE))
            {
                pEvent->type = EN_MAC_TX_EVENT_TYPE_SEND_DONE;
                pEvent->data = (getMacTxStateEventValue(EN_MAC_TX_EVENT_TYPE_SEND_DONE));
            }
            break;    
        case EN_MAC_TX_STATE_WAIT_ACK:
            if(getMacTxStateEventType(EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE))
            {
                pEvent->type = EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE;
                pEvent->data = (getMacTxStateEventValue(EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE));
            }            
            break;    
        case EN_MAC_TX_STATE_SUCCED:
            if(getMacTxStateEventType(EN_MAC_TX_EVENT_TYPE_TRANS_FINISH))
            {
                pEvent->type = EN_MAC_TX_EVENT_TYPE_TRANS_FINISH;
            }            
            break;    
        case EN_MAC_TX_STATE_FAILED:
            if(getMacTxStateEventType(EN_MAC_TX_EVENT_TYPE_TRANS_FINISH))
            {
                pEvent->type = EN_MAC_TX_EVENT_TYPE_TRANS_FINISH;
            }            
            break;
    }

    if(pEvent->type != EN_MAC_TX_EVENT_TYPE_NONE)
    {
        return true;
    }
    return false;

}

int macTxStateMachineRun(STATEM_TYPE_ST* pEvent) //pEvent入参
{
    STATE_MACHINE_HANDLE_RESULT_EN statMret = stateM_errArg;
    
    int ret = -1;
    if(NULL == pEvent)
    {
        return ret;
    }

    do
    {
        if(statMret == stateM_stateNextContinue)
        {
            macTxStateMachineEventCheck(pEvent);
        }

        clearMacTxStateEventType(pEvent->type); //check后，在handleEvent处理该事件前，clear之
        if(pEvent->type != EN_MAC_TX_EVENT_TYPE_NONE) //表明有事件正需要处理，可作为休眠判断条件，休眠前需临界资源保护之，关闭全局中断.
        {
            statMret = stateM_handleEvent(&s_instTxStateMachine,pEvent);
            ret = 0;
        }
        else
        {
            break;
        } 

        if(statMret == stateM_stateChanged || statMret == stateM_stateNextContinue)
        {
            if(get_mac_printf_log())
              printf("T %d-%d\r\n",((TX_STATE_CTRL_BLOCK_ST*)(s_instTxStateMachine.ctrlData))->enHandlingEventType,s_instTxStateMachine.currentState->handle);
            switch(s_instTxStateMachine.previousState->handle)
            {
                case EN_MAC_TX_STATE_SEND:
                    if(waitSendTimer.status != EN_MULTITIMER_STATUS_IDLE)
                    {
                        softwareMultiTimerStop(MAC_TX_STATEMACHINE_HARD_TIMER,&waitSendTimer,0);//退出该状态时，关闭相关定时器，该定时器需留余量
                    }
                    break;
                case EN_MAC_TX_STATE_WAIT_ACK:
                    if(waitAckTimer.status != EN_MULTITIMER_STATUS_IDLE)
                    {
                        softwareMultiTimerStop(MAC_TX_STATEMACHINE_HARD_TIMER,&waitAckTimer,0);//退出该状态时，关闭相关定时器 
                    }          
                    break;   
            } 
        }                      

    } while (statMret == stateM_stateNextContinue);
    
    return ret;
}

static int txCallback(STATEM_STATE_MACHINE_ST* fsm)
{
    //uint8_t temp8;
    int ret = -1;
    TX_STATE_CTRL_BLOCK_ST *pstFsmData = (TX_STATE_CTRL_BLOCK_ST *) fsm->ctrlData;
    RETRY_CTRL_ST* pstRetryCtrl = NULL;  
    //组包回调
    if(fsm->currentState->handle == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE)
    {
        pstFsmData->pPacketToSend = NULL;
    }

    pstRetryCtrl = getRetryCtrlBlock(pstFsmData,pstFsmData->enHandlingEventType);
    if(pstFsmData->ppMacCallbackTx[pstFsmData->enHandlingEventType] != NULL)
    {
        pstFsmData->ppMacCallbackTx[pstFsmData->enHandlingEventType] (&(pstFsmData->pPacketToSend), fsm->currentState->handle, pstRetryCtrl);
        ret = 0;
    }

    if( (fsm->currentState->handle == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE) & (pstFsmData->pPacketToSend == NULL) )
    {
        if(get_mac_printf_log())
          printf("TE%d Pnu!",pstFsmData->enHandlingEventType);
        if(pstRetryCtrl != NULL)
        {
            pstRetryCtrl->byRetryMaxTimes = 0;
            pstRetryCtrl->byRetryCount = 0;
            printf("CC");//取消重传
        }
        if(get_mac_printf_log())
          printf("\r\n");
        ret = -1;
    }    

    return ret;
}


/***********************************************状态机相关函数指针定义****************************************************************************/

/**call the TDMA  get当前的RTC时间，并检查当前是否避开TimeSlotAssigned，需考虑包长以保证报文尾处避开，仅Adhoc需要（其中 已分配slot的SPVN、文件数据报文，无需检查）
 * 若检查通过则 回调上层组包，填充负载数据或直接获取MAC报文指针，AES加密，可考虑切出，加密完成后，
  * 再执行Action，写TX_FIFO，若不通过清除切出 等待定时器延时到下一个可用非规划slot的时间点 再置位执行*/
static bool transReqEventGuard(STATEM_STATE_MACHINE_ST* fsm, void* condition, STATEM_TYPE_ST *event)//Todo,减少循环次数
{
    uint32_t dwCondition = (uint32_t)condition;
    TX_STATE_CTRL_BLOCK_ST *pstFsmData = (TX_STATE_CTRL_BLOCK_ST *) fsm->ctrlData;
    STATEM_TYPE_ST  stRxStateEvent;
    int i;
    uint32_t temp32 = 0;
    RETRY_CTRL_ST* pstRetryCtrl = NULL;
    int tempi = 0;
    //按优先顺序遍历发送请求，
    if(dwCondition & (getMacTransEventBitMask()))
    {
        for(i=0;i<EN_TRANS_REQ_MAX;i++)
        {
            temp32 = GET_DW_BIT_MASK(i);
            if((getMacTransEventBitMask()) & temp32 & dwCondition)
            {
                if(temp32 & TRANS_EVENT_LBT_NOT_NEED_BITMASK)//可打断接收过程，强制发送here，高优先级的发送任务 可打断 接收任务,ToDo打断后做好记录
                {
                    clearTransEventBitMask(temp32); //clear this event，debug here！置位操作在A线程，清除操作在B线程，造成多线程异常，已加保护； 
                    pstFsmData->enHandlingEventType = i;
                    //回调上层组包
                    if(txCallback(fsm) >= 0)
                    {
                        //printf("【%d-%lu-%lu】\r\n",i,temp32,getMacTransEventBitMask());//可删除
                        return true;    
                    }
                } 
                else //需要LBT的传输事件
                {
                  tempi = checkChannelSlotAvailable(s_pTransEventDestId[i],i);
                  if(tempi >= 0) //需LBT的都先进行Slot槽检测
                  {
                      if(CHECK_RF_TX_IDLE) //ToDo 发送前准备，下一个状态为LBTCHECK!
                      {
                          clearTransEventBitMask(temp32); //满足条件 则直接clear this transReq event;
                          pstFsmData->enHandlingEventType = i; //Uplink类有2个trans_req，adhoc_uplink和 spvn，已在setTransEvent()侧进行互斥
                          pstRetryCtrl = getRetryCtrlBlock(pstFsmData,i);//指针返回时 必须判断是否空
                          if(pstRetryCtrl != NULL){
                            if(pstRetryCtrl->byRetryCount > RETRY_TIMES_MIN_TRY_RESYNC || pstFsmData->enHandlingEventType == EN_TRANS_REQ_REGISTER) //重传次数超过一定数时或注册请求报文或请求漫游的报文 使用备用信道 ToDo 动态调整发射功率，应在开始LBT时决定
                            {
                                s_TxWaitAckChannel = getAccessChan(CHAN_TYPE_RESYNC);//需在LBT前决定监听信道
                            }
                            else
                            {
                                s_TxWaitAckChannel = getAccessChan(CHAN_TYPE_MAIN);
                            }
                          }
                          else //无需应答的事件 选择当前主信道
                          {
                              s_TxWaitAckChannel = getAccessChan(CHAN_TYPE_MAIN);//需在LBT前决定监听信道
                          }
                          setMacRecvEvent(EN_RECV_REQ_LISTEN_BACKRSSI_WINDOW, s_TxWaitAckChannel);//开启Rx接收,Todo 此处需指定信道
                          macRxStateMachineEventCheck(&stRxStateEvent);//ToDo， 对于RFM角色 listen rssi 不收包？ 只做CCA？
                          macRxStateMachineRun(&stRxStateEvent);//zz,注意在TxState状态机内调用了RxState状态机，是否合法？？
                          //回调上层组包
                          if(txCallback(fsm) >= 0)
                          {
                              return true;
                          }

                      }
                      else //RF正在忙
                      {
                          //ToDo
                          return false; //不满足条件，不清除事件，轮询RF等待其空闲，并阻止休眠；Todo 此处可开启最大超时软定时器，巡检异常情况，防止射频芯片不空闲异常；
                      }
                  }
                  else//增加一定的随机延时，发送时刻分配时间槽冲突，若不满足slotAvailable槽条件，可先清除该事件bit，类似LBT，新增标志位 低功耗延时避开当前已分配槽后callback再置位bit
                  {
                      //ToDo 退避繁忙窗口
                      tempi = 0 - tempi;
                      softwareMultiTimerStart(MAC_TX_STATEMACHINE_HARD_TIMER,&waitValidSlotTimer,tempi+(rand_()&0x03FF),waitValidSlotTimerCallback , NULL ,1);//进入该状态时 打开定时器计超时
                      return false; //暂时，待修改
                  }
                }
            }
        }    
    }

    return false;
}

//WriteFifo
/**在非加密认证段打上本地时间戳后将所有待发送数据写入TX Fifo,直接跳转到TxStateLbtCheck状态执行; 若处于Rxing则 切出 到TxStateSlotCheck状态 等待延时后执行*/
static bool transReqEventActionSend(STATEM_STATE_MACHINE_ST* fsm, STATEM_TYPE_ST *event)
{
    TX_STATE_CTRL_BLOCK_ST *pstFsmData = (TX_STATE_CTRL_BLOCK_ST *) fsm->ctrlData;
    uint8_t chan = 0;
    /***ToDo 计算发送信道，可打断正在接收状态，强制发送，并告知接收状态机，接收过程被打断，接收状态机可跳转至失败**/
    //ToDo 若接收被发送打断 需告知接收处理状态机，清除接收相关事件；
    //AddTimeStamp,ToDo 可临界保护之
    uint32_t temp32 = 0;
    uint8_t byAntIdx = 0xFF;//随机天线选择
    static uint8_t sSyncBcastAntIdx = 0;

    if(pstFsmData->enHandlingEventType == EN_TRANS_REQ_SYNC_BCAST)
    {
        byAntIdx = sSyncBcastAntIdx;
        if(0 == sSyncBcastAntIdx)
          sSyncBcastAntIdx = 1;
        else
          sSyncBcastAntIdx = 0;

        temp32 = 1604;
        if(wTxPreambleLen != BCAST_PREAMBLE_LENGTH_BIT)
        {
            bsp_rf_set_tx_preambleLen(BCAST_PREAMBLE_LENGTH_BIT);
            wTxPreambleLen = BCAST_PREAMBLE_LENGTH_BIT;
            printf("P%d",wTxPreambleLen);
        }
    }
    else if(pstFsmData->enHandlingEventType == EN_TRANS_REQ_ADHOC_SPVN_ACK)
    {
        temp32 = 0; //默认40bit
        if(wTxPreambleLen != ACK_PREAMBLE_LENGTH_BIT) //待修改，对方接收是否跳频？
        {
            bsp_rf_set_tx_preambleLen(ACK_PREAMBLE_LENGTH_BIT);
            wTxPreambleLen = ACK_PREAMBLE_LENGTH_BIT;
        }
    }
    else
    {
        temp32 = 81;//adhoc前导码改为135bit，比默认40bit增加95bit故补偿81，（40bit补偿34）
        if(wTxPreambleLen != ADHOC_PREAMBLE_LENGTH_BIT) //
        {
            bsp_rf_set_tx_preambleLen(ADHOC_PREAMBLE_LENGTH_BIT);
            wTxPreambleLen = ADHOC_PREAMBLE_LENGTH_BIT;
        }
    }

    if(pstFsmData->enHandlingEventType == EN_TRANS_REQ_ADHOC_SPVN_ACK)
    {
        chan = s_RecvAckChannel;
    }
    else
    {
        chan = getAccessChan(CHAN_TYPE_MAIN);
    }

    //加时间戳并发送，以下考虑提高效率，memcpy方式？ToDo，并加临界保护
    temp32 = READ_BU_RTC_COUNT() + temp32;
    pstFsmData->pPacketToSend[7+MAC_LAYER_PACKET_SYNC_TIME_OFFSET] = (uint8_t)temp32;//
    temp32 = temp32>>8;
    pstFsmData->pPacketToSend[6+MAC_LAYER_PACKET_SYNC_TIME_OFFSET] = (uint8_t)(temp32);//
    temp32 = temp32>>8;
    pstFsmData->pPacketToSend[5+MAC_LAYER_PACKET_SYNC_TIME_OFFSET] = (uint8_t)(temp32);//
    writeTxFifo(pstFsmData->pPacketToSend,false);
    //startTx(getAccessChan(CHAN_TYPE_MAIN));//ToDo，若为应答ACK发送 则应在收到的信道上应答？0814 已do
    startTx(chan,byAntIdx);

    clearMacTxStateEventType(EN_MAC_TX_EVENT_TYPE_SEND_DONE);
    softwareMultiTimerStart(MAC_TX_STATEMACHINE_HARD_TIMER,&waitSendTimer,WAIT_SEND_TIMEOUT, waitSendTimerCallback, NULL ,1);//进入该状态时 打开定时器计超时
    PRINTF_PACKET(pstFsmData->pPacketToSend);
    return false;                     
}

//do PACKET_ASSEMBLE and WriteFifo
/**若仍处于RxListenBackRssi，则在非加密认证段打上本地时间戳后将所有待发送数据写入TX Fifo,直接跳转到TxStateLbtCheck状态执行; 若处于Rxing则 切出 到TxStateSlotCheck状态 等待延时后执行*/
static bool transReqEventActionLbt(STATEM_STATE_MACHINE_ST* fsm, STATEM_TYPE_ST *event)
{
#ifdef LBT_TX_WRITE_FIFO_FIRST
    TX_STATE_CTRL_BLOCK_ST *pstFsmData = (TX_STATE_CTRL_BLOCK_ST *) fsm->ctrlData;
    //AddTimeStamp
    uint32_t temp32 = READ_BU_RTC_COUNT();
    pstFsmData->pPacketToSend[7+MAC_LAYER_PACKET_SYNC_TIME_OFFSET] = (uint8_t)temp32;//
    temp32 = temp32>>8;
    pstFsmData->pPacketToSend[6+MAC_LAYER_PACKET_SYNC_TIME_OFFSET] = (uint8_t)(temp32);//
    temp32 = temp32>>8;
    pstFsmData->pPacketToSend[5+MAC_LAYER_PACKET_SYNC_TIME_OFFSET] = (uint8_t)(temp32);//

    writeTxFifo(pstFsmData->pPacketToSend,true);
#endif
    //set lbt event
    setMacTxStateEvent(EN_MAC_TX_EVENT_TYPE_LBT_CHECK_DONE,0);
    return true;                         
}

/**getRFstate, 若仍处于RxListenBackRssi，经过前面切出延时后，可读取实时信号强度，若符合阈值条件，则直接跳转到TxStateSend状态执行
 * 若状态变为RXing 或不符合条件，则切出 到TxStateSlotCheck状态 等待延时后执行.
*/
static bool doLbtCheckEventGuard(STATEM_STATE_MACHINE_ST* fsm, void* condition, STATEM_TYPE_ST *event)//event data未使用
{
    bool ret = false;
    uint32_t dwCondition = (uint32_t)condition;
    TX_STATE_CTRL_BLOCK_ST *pstFsmData = (TX_STATE_CTRL_BLOCK_ST *) fsm->ctrlData;
    //是否仍处于CHECK_RF_TX_IDLE状态,相当于有干扰存在
    if(
        CHECK_RF_TX_IDLE  //RF芯片的状态为空闲
        && (!(getMacTransEventBitMask() & TRANS_EVENT_LBT_NOT_NEED_BITMASK))//当不存在 其他免LBT事件时 才LBT通过，Add1008
        && (checkLbtRssiIsPass() || pstFsmData->stLbtCtrl.byLbtCount >= pstFsmData->stLbtCtrl.byLbtMaxTimes)//处于接收状态读取信号强度通过，或者LBT次数超过最大允许值
    )//超出LBT最大次数强制发送 ToDo是否需避免非TX IDLE正接收报文状态
    {
        ret = true;
    }
    return ret;
}

static bool doLbtCheckEventActionSend(STATEM_STATE_MACHINE_ST* fsm, STATEM_TYPE_ST *event)
{
    TX_STATE_CTRL_BLOCK_ST *pstFsmData = (TX_STATE_CTRL_BLOCK_ST *) fsm->ctrlData;
    uint32_t temp32 = 0;
    uint8_t temp8 = 0;
    uint8_t byAntIdx = 0xFF;//随机天线选择
    static uint8_t sDownLinkAntIdx[DOWNLINK_CONCURRENCY_CAPABILITY] = {0,0,0,0,0};
    static uint8_t sRealTimeBcastAntIdx = 0;

    if(pstFsmData->enHandlingEventType == EN_TRANS_REQ_REALTIME_BCAST) //主动实时广播下行
    {
        byAntIdx = sRealTimeBcastAntIdx;
        if(0 == sRealTimeBcastAntIdx)
          sRealTimeBcastAntIdx = 1;
        else
          sRealTimeBcastAntIdx = 0;
    }
    else if (EN_TRANS_REQ_ADHOC_DOWNLINK_START <= pstFsmData->enHandlingEventType && pstFsmData->enHandlingEventType <= EN_TRANS_REQ_ADHOC_DOWNLINK_END)//主动点对点下行
    {
        temp8 = pstFsmData->enHandlingEventType-EN_TRANS_REQ_ADHOC_DOWNLINK_START;
        byAntIdx = sDownLinkAntIdx[temp8];
        if(0 == sDownLinkAntIdx[temp8])
          sDownLinkAntIdx[temp8] = 1;
        else
          sDownLinkAntIdx[temp8] = 0;
    }

    temp32 = 81;//adhoc前导码改为135bit，比默认40bit增加95bit故补偿81，（40bit补偿34）
    if(wTxPreambleLen != ADHOC_PREAMBLE_LENGTH_BIT) //ToDo 待修改，是否移动至 transEventGuard内
    {
        bsp_rf_set_tx_preambleLen(ADHOC_PREAMBLE_LENGTH_BIT);
        wTxPreambleLen = ADHOC_PREAMBLE_LENGTH_BIT;
    }

    /***ToDo 可打断正在接收状态，强制发送，并告知接收状态机，接收过程被打断，接收状态机可跳转至失败**/
#ifndef LBT_TX_WRITE_FIFO_FIRST
    //AddTimeStamp
    temp32 = READ_BU_RTC_COUNT() + temp32;
    pstFsmData->pPacketToSend[7+MAC_LAYER_PACKET_SYNC_TIME_OFFSET] = (uint8_t)temp32;//
    temp32 = temp32>>8;
    pstFsmData->pPacketToSend[6+MAC_LAYER_PACKET_SYNC_TIME_OFFSET] = (uint8_t)(temp32);//
    temp32 = temp32>>8;
    pstFsmData->pPacketToSend[5+MAC_LAYER_PACKET_SYNC_TIME_OFFSET] = (uint8_t)(temp32);//
    writeTxFifo(pstFsmData->pPacketToSend,true);
#endif

    startTx(s_TxWaitAckChannel,byAntIdx);

    clearMacTxStateEventType(EN_MAC_TX_EVENT_TYPE_SEND_DONE);
    softwareMultiTimerStart(MAC_TX_STATEMACHINE_HARD_TIMER,&waitSendTimer,WAIT_SEND_TIMEOUT, waitSendTimerCallback, NULL ,1);//进入该状态时 打开定时器计超时
    //clear lbt crtl data
    pstFsmData->stLbtCtrl.byLbtCount = 0;
    //pstFsmData->stLbtCtrl.byLbtMaxTimes = 0; //该标志无需清0，bug清0后会导致 LBT重试添加的事件无法设置LbtMaxTime而异常
    PRINTF_PACKET(pstFsmData->pPacketToSend);

    return false;
}

static uint32_t getLbtTimerDelay(TRANS_REQ_E transE ,LBT_CTRL_ST *pstLBTCtrl)
{
  uint32_t temp32 = 0;

  /*if(transE == EN_TRANS_REQ_REGISTER)
  {
      temp32 = 32768;
  }
  else*/
  if(pstLBTCtrl->byLbtCount  < LBT_REDO_COUNT_MAX)
  {
      srand_(READ_SYS_RTC_COUNT());
      temp32 = lbtDelayTime[pstLBTCtrl->byLbtCount] + rand_() % lbtDelayTime[pstLBTCtrl->byLbtCount]; //ToDo random函数的耗时？改造成硬件随机数？
  }
  else
  {
      temp32 = 0x3FF + (rand_() & 0x3FF);
  }

  return temp32;
}


static bool doLbtCheckEventActionIdle(STATEM_STATE_MACHINE_ST* fsm, STATEM_TYPE_ST *event)
{
    TX_STATE_CTRL_BLOCK_ST *pstFsmData = (TX_STATE_CTRL_BLOCK_ST *) fsm->ctrlData;   
    uint32_t temp32;
    if(lbtTimer.status != EN_MULTITIMER_STATUS_IDLE)//已存在旧的lbt事件，清除并立即回调产生事件标志，让给优先级高的新事件使用
    {
        softwareMultiTimerStop(MAC_TX_STATEMACHINE_HARD_TIMER,&lbtTimer,1);// call expire callback   
        //s_stTxCtrlBlock.stLbtCtrl.byLbtCount = 0;// todo 是否将lbt count重置，bug重置后陷入死循环，除非派生出多个lbt定时器实例。              
        printf("INT&%d",pstFsmData->enHandlingEventType);
    }
    temp32 = getLbtTimerDelay(pstFsmData->enHandlingEventType,&(pstFsmData->stLbtCtrl));
    //开启重做lbt定时器，以重新置位发送请求事件，并跳到Idle, ToDo random函数的耗时？改造成硬件随机数？
    softwareMultiTimerStart(MAC_TX_STATEMACHINE_HARD_TIMER,&lbtTimer,temp32, lbtTimerCallback, (void*)(pstFsmData->enHandlingEventType) ,0);//ToDo debug
    pstFsmData->stLbtCtrl.byLbtCount ++;
    printf("LF%d*%d-%d",pstFsmData->enHandlingEventType,pstFsmData->stLbtCtrl.byLbtCount,pstFsmData->stLbtCtrl.byLbtMaxTimes);//LBT失败

    return false;
}

/*******************************************************/
static bool sendResultAckReqEventGuard(STATEM_STATE_MACHINE_ST* fsm, void* condition, STATEM_TYPE_ST *event)
{
    bool ret = false;    
    if(!CHECK_TRANS_EVENT_TYPE_IS_ACK_NOT_REQ(((TX_STATE_CTRL_BLOCK_ST *)(fsm->ctrlData))->enHandlingEventType))
    {
        if((uint8_t)condition == (uint8_t)(event->data))
        {
            ret = true;
        }
    }

    return ret;
}

static bool sendResultAckNotReqEventGuard(STATEM_STATE_MACHINE_ST* fsm, void* condition, STATEM_TYPE_ST *event)
{
    bool ret = false; 
    if(CHECK_TRANS_EVENT_TYPE_IS_ACK_NOT_REQ(((TX_STATE_CTRL_BLOCK_ST *)(fsm->ctrlData))->enHandlingEventType))
    {
        if((uint8_t)condition == (uint8_t)(event->data))
        {
            ret = true;
        }
    }

    return ret;      
}

static bool sendResultEventActionWaitAck(STATEM_STATE_MACHINE_ST* fsm,  STATEM_TYPE_ST *event)
{
    //startRx ack window 强制开启
    setMacRecvEvent(EN_RECV_REQ_ACK_WINDOW,s_TxWaitAckChannel);//开启Rx接收,Todo 此处需指定信道
    //macRxStateMachineRun();//zz,注意在TxState状态机内调用了RxState状态机，是否合法? 屏蔽此处 考虑到HUB应答延时，无需及时开启接收
    //start ack wait timout
    clearMacTxStateEventType(EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE);
    softwareMultiTimerStart(MAC_TX_STATEMACHINE_HARD_TIMER,&waitAckTimer,WAIT_ACK_TIMEOUT, waitAckTimerCallback, NULL ,1);//ToDo debug
    return false;
}

static bool sendResultEventActionFinish(STATEM_STATE_MACHINE_ST* fsm,  STATEM_TYPE_ST *event)
{
    setMacTxStateEvent(EN_MAC_TX_EVENT_TYPE_TRANS_FINISH,0);
    return true;
}


static uint32_t getRetryTimerDelay(TRANS_REQ_E transE ,RETRY_CTRL_ST *pstRetryCtrl)
{
  uint32_t temp32 = 0;

  if(transE == EN_TRANS_REQ_REGISTER)
  {
      uint8_t mac[8];
      getMacAddr(mac);
      srand_(READ_SYS_RTC_COUNT() + mac[7]);
      temp32 = 58982 + rand_() % 13107;  //1.8s - 2.2s 随机
  }
  else if(pstRetryCtrl->byRetryCount  < ADHOC_RETRY_COUNT_MAX)
  {
      srand_(READ_SYS_RTC_COUNT());
      temp32 = retryDelayTime[pstRetryCtrl->byRetryCount] + rand_() % retryDelayTime[pstRetryCtrl->byRetryCount]; //ToDo random函数的耗时？改造成硬件随机数？
  }
  else
  {
      temp32 = 16384 + (rand_() & 0x3FFF);
  }

  return temp32;
}


static bool sendResultEventActionRetryIdle(STATEM_STATE_MACHINE_ST* fsm,  STATEM_TYPE_ST *event)
{
    uint8_t temp8;
    uint32_t temp32;
    RETRY_CTRL_ST* pstRetryCtrl = NULL;
    TX_STATE_CTRL_BLOCK_ST *pstFsmData = (TX_STATE_CTRL_BLOCK_ST *) fsm->ctrlData;  
  
    pstRetryCtrl = getRetryCtrlBlock(pstFsmData,pstFsmData->enHandlingEventType);
    if(pstRetryCtrl != NULL && pstRetryCtrl->byRetryMaxTimes != 0)
    {
        if(pstRetryCtrl->stRetryTimer.status != EN_MULTITIMER_STATUS_IDLE)
        {
            softwareMultiTimerStop(MAC_TX_STATEMACHINE_HARD_TIMER,&(pstRetryCtrl->stRetryTimer),0);//直接打断，不允许恢复之，心跳打断心跳会进来，adhoc打断心跳应在前面set已打断，同后应答失败retry
            printf("TF%dINT%d!",pstRetryCtrl->byEventType,pstFsmData->enHandlingEventType);//上个发送事件被打断，一般是心跳被adhoc打断，但是，在setMacTransEvent已做过拦截，将重传定时器关闭，此处仅是保险
        }
        
        temp32 = getRetryTimerDelay(pstFsmData->enHandlingEventType,pstRetryCtrl);
        softwareMultiTimerStart(MAC_TX_STATEMACHINE_HARD_TIMER,&(pstRetryCtrl->stRetryTimer),temp32, retryTimerCallback, (void*)(pstRetryCtrl->byEventType) ,0); //针对上行的心跳事件被INPUT打断 ，可能enHandlingEventType == 心跳，导致心跳事件又重传产生；修改为pstRetryCtrl->byEventType，可能出现重传重复置位的情况

        printf("TF%dR%d-%d",pstFsmData->enHandlingEventType,pstRetryCtrl->byRetryCount,pstRetryCtrl->byRetryMaxTimes);//传输失败，重传
    }
    else
    {
        printf("ET?");
    }

    return false;
}

#define TRANS_FAILED_TIMES_NO_MOER_RETRY  200//每次重传10
#define TRANS_FAILED_TIMES_LOSS_TIME_SYNC 100 //每次重传10
static uint16_t s_transRetryFailedCount = 0;
/*******************************************************/
static bool waitAckResultEventGuard(STATEM_STATE_MACHINE_ST* fsm, void* condition, STATEM_TYPE_ST *event)
{
    bool ret = false;
    uint8_t byCondition = (uint8_t)condition;
    uint8_t byEventData = (uint8_t)(event->data);    
    RETRY_CTRL_ST* pstRetryCtrl = NULL;    
    TX_STATE_CTRL_BLOCK_ST *pstFsmData = (TX_STATE_CTRL_BLOCK_ST *) fsm->ctrlData;  

    pstRetryCtrl = getRetryCtrlBlock(pstFsmData,pstFsmData->enHandlingEventType);
    if(pstRetryCtrl != NULL && pstRetryCtrl->byRetryMaxTimes != 0  //重传事件且重传标志仍在
        /*&& (pstRetryCtrl->byRetryCount < pstRetryCtrl->byRetryMaxTimes || byEventData == WAIT_ACK_DONE_IS_PASS)*/ // ToDo，应该是个bug，如果在最后1次收到应答，retryCount = RetryMaxTimes 增加|| byEventData == WAIT_ACK_DONE_IS_PASS
    )
    {
        if(byCondition == byEventData)
        {
            ret = true;
            //收到应答
            if(byEventData == WAIT_ACK_DONE_IS_PASS)
            {
              s_transRetryFailedCount = 0;
            }
            //超时未收到应答
            else
            {
              if(pstFsmData->enHandlingEventType == EN_TRANS_REQ_ADHOC_UPLINK || pstFsmData->enHandlingEventType == EN_TRANS_REQ_SPVN)
              {
                  s_transRetryFailedCount++; //允许其翻转，65535次失败后，重传次数将增加
              }

              //发送失败判定
              if(
                  (pstRetryCtrl->byRetryCount >= pstRetryCtrl->byRetryMaxTimes) // 重传次数超过最大允许次数，即认定传输失败
                ||((pstFsmData->enHandlingEventType != pstRetryCtrl->byEventType) && (getMacTransEventBitMask() & GET_DW_BIT_MASK(pstRetryCtrl->byEventType))) //add0928 当前状态事件和待重传事件不匹配，且该待重传事件有请求标志时，认定当前状态事件不再重传而失败。
                 )
              {
                  ret = false;
              }
#ifdef RFM_DEVICE
              if( (pstFsmData->enHandlingEventType == EN_TRANS_REQ_ADHOC_UPLINK || pstFsmData->enHandlingEventType == EN_TRANS_REQ_SPVN)
                  && s_transRetryFailedCount >= TRANS_FAILED_TIMES_NO_MOER_RETRY
                  )//连续失败超过200次，不再重传，结束本次传输，并置失败； ToDo，需考虑漫游请求的场景
              {
                  ret = false;
              }
              //心跳始终失败，表示与网关失去时间同步，此时均往备用信道发数据，并考虑停止RxWake
              if(s_transRetryFailedCount >= TRANS_FAILED_TIMES_LOSS_TIME_SYNC)
              {
                  clearTimeSyncedFlag();
              }
#endif
            }
        }
    }
    return ret;  
}

static bool waitAckResultEventActionFinish(STATEM_STATE_MACHINE_ST* fsm,  STATEM_TYPE_ST *event)
{
    uint8_t temp8;
    RETRY_CTRL_ST* pstRetryCtrl = NULL;
    TX_STATE_CTRL_BLOCK_ST *pstFsmData = (TX_STATE_CTRL_BLOCK_ST *) fsm->ctrlData;  
    
    pstRetryCtrl = getRetryCtrlBlock(pstFsmData,pstFsmData->enHandlingEventType);
    if(pstRetryCtrl != NULL && pstRetryCtrl->byRetryMaxTimes != 0 )//Bug adhoc或重新使能心跳、打断心跳后，若心跳接收成功，则会将该RetryMaxTime清0，需新赋值正确值，fixed 0915，识别到事件相等，且无开启标志 才将retryMaxTimes清0；
    {
        pstRetryCtrl->byRetryCount = 0;
        if(
            (pstFsmData->enHandlingEventType == pstRetryCtrl->byEventType) && (!(getMacTransEventBitMask() & GET_DW_BIT_MASK(pstRetryCtrl->byEventType)))
           ) //fixed 0915 防止adhoc将正运行的spvn打断后，maxtimes清0的异常，即仅在当 当前状态机处理事件与重传控制的事件相同，且传输请求标志未清0
        {
            pstRetryCtrl->byRetryMaxTimes = 0;
        }
        pstRetryCtrl->bySeq ++;
    }
    else//可删除
    {
        printf("ET&\r\n");
    }

    setMacTxStateEvent(EN_MAC_TX_EVENT_TYPE_TRANS_FINISH,0);
    return true;
}

static bool waitAckResultEventActionRetryIdle(STATEM_STATE_MACHINE_ST* fsm, STATEM_TYPE_ST *event)
{
    uint8_t temp8;
    uint32_t temp32 = 0;
    RETRY_CTRL_ST* pstRetryCtrl = NULL;
    TX_STATE_CTRL_BLOCK_ST *pstFsmData = (TX_STATE_CTRL_BLOCK_ST *) fsm->ctrlData;  
    
    pstRetryCtrl = getRetryCtrlBlock(pstFsmData,pstFsmData->enHandlingEventType);
    if(pstRetryCtrl != NULL && pstRetryCtrl->byRetryMaxTimes != 0 && pstRetryCtrl->byRetryCount < pstRetryCtrl->byRetryMaxTimes)
    {
        if(pstRetryCtrl->stRetryTimer.status != EN_MULTITIMER_STATUS_IDLE)
        {
            softwareMultiTimerStop(MAC_TX_STATEMACHINE_HARD_TIMER,&(pstRetryCtrl->stRetryTimer),0);//直接打断，不允许恢复之，心跳打断心跳会进来，adhoc打断心跳应在前面set已打断
            printf("RT%dI%d",pstRetryCtrl->byEventType,pstFsmData->enHandlingEventType);
        }
        temp32 = getRetryTimerDelay(pstFsmData->enHandlingEventType,pstRetryCtrl);
        softwareMultiTimerStart(MAC_TX_STATEMACHINE_HARD_TIMER,&(pstRetryCtrl->stRetryTimer),temp32, retryTimerCallback, (void*)(pstRetryCtrl->byEventType) ,0);//针对上行的心跳事件被INPUT打断 ，可能enHandlingEventType == 心跳，导致心跳事件又产生
        pstRetryCtrl->byRetryCount ++;
        printf("E%dRN%d-%d",pstFsmData->enHandlingEventType,pstRetryCtrl->byRetryCount,pstRetryCtrl->byRetryMaxTimes);
    }
    else//可删除
    {
        printf("ET#");
    }

    return false;    
}


/*******************************************************/
static bool transSuccedEventAction(STATEM_STATE_MACHINE_ST* fsm, STATEM_TYPE_ST *event)
{
    txCallback(fsm);//此处 retry字段已清除
    return false;
}

static bool transFailedEventAction(STATEM_STATE_MACHINE_ST* fsm, STATEM_TYPE_ST *event)
{
    txCallback(fsm);
    return false;
}


static STATEM_STATE_ST pstTxState[EN_MAC_TX_STATE_MAX] = 
{
/**没有处于发送态，主动上报事件处理active transfer Event； 由于RF芯片半双工，首先 getRFstate, 若处于idle、RxWaitPreamble 则针对 aloha： adhoc事件 ; TimeSlotAssigned: Spvn 事件，直接跳转到TxStatePacketAssemble执行； 
 * 针对这些需LBT的任务 还需同时 切出传递事件给RfstateMachine（或直接调用RAIL库）将RFstate置为RxListenBackRssi, 执行将RF芯片切为RX Listen*/
//EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE 
{
    .handle = EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE,
    .numTransitions = 2,
    .transitions = (STATEM_TRANSITION_ST[])
    {
        {EN_MAC_TX_EVENT_TYPE_TRANS_REQ,TRANS_EVENT_LBT_NOT_NEED_BITMASK,transReqEventGuard,transReqEventActionSend ,&(pstTxState[EN_MAC_TX_STATE_SEND]) },//Firstly
        {EN_MAC_TX_EVENT_TYPE_TRANS_REQ,(~TRANS_EVENT_LBT_NOT_NEED_BITMASK),transReqEventGuard,transReqEventActionLbt ,&(pstTxState[EN_MAC_TX_STATE_LBT_CHECK]) },//secondly
    },

},


/**getRFstate, 若仍处于RxListenBackRssi，经过前面切出延时后，可读取实时信号强度，若符合阈值条件，则直接跳转到TxStateSend状态执行
 * 若状态变为RXing 或不符合条件，则切出 到TxStateSlotCheck状态 等待延时后执行.
*/
//EN_MAC_TX_STATE_LBT_CHECK
{
    .handle = EN_MAC_TX_STATE_LBT_CHECK,
    .numTransitions = 2,
    .transitions = (STATEM_TRANSITION_ST[])
    {
        {EN_MAC_TX_EVENT_TYPE_LBT_CHECK_DONE,NULL,doLbtCheckEventGuard,doLbtCheckEventActionSend,&(pstTxState[EN_MAC_TX_STATE_SEND])},
        {EN_MAC_TX_EVENT_TYPE_LBT_CHECK_DONE,NULL,NULL,doLbtCheckEventActionIdle,&(pstTxState[EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE])}
    },

},

/*
*此处将强制切换RF状态至发送态
*/
//EN_MAC_TX_STATE_SEND
{
    .handle = EN_MAC_TX_STATE_SEND,
    .numTransitions = 4,
    .transitions = (STATEM_TRANSITION_ST[])
    {
        {EN_MAC_TX_EVENT_TYPE_SEND_DONE,SEND_DONE_IS_PASS, sendResultAckReqEventGuard, sendResultEventActionWaitAck,&(pstTxState[EN_MAC_TX_STATE_WAIT_ACK])},
        {EN_MAC_TX_EVENT_TYPE_SEND_DONE,!SEND_DONE_IS_PASS, sendResultAckReqEventGuard, sendResultEventActionRetryIdle,&(pstTxState[EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE])},            
        {EN_MAC_TX_EVENT_TYPE_SEND_DONE,SEND_DONE_IS_PASS,sendResultAckNotReqEventGuard,sendResultEventActionFinish,&(pstTxState[EN_MAC_TX_STATE_SUCCED])},
        {EN_MAC_TX_EVENT_TYPE_SEND_DONE,!SEND_DONE_IS_PASS,sendResultAckNotReqEventGuard,sendResultEventActionFinish,&(pstTxState[EN_MAC_TX_STATE_FAILED])},
    },  
},


/*
* 将RxState置为ACK_WINDOW
*/
//EN_MAC_TX_STATE_WAIT_ACK 
{
    .handle = EN_MAC_TX_STATE_WAIT_ACK,
    .numTransitions = 3,
    .transitions = (STATEM_TRANSITION_ST[])
    {     
        {EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE,WAIT_ACK_DONE_IS_PASS,waitAckResultEventGuard,waitAckResultEventActionFinish,&(pstTxState[EN_MAC_TX_STATE_SUCCED])},
        {EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE,!WAIT_ACK_DONE_IS_PASS,waitAckResultEventGuard,waitAckResultEventActionRetryIdle,&(pstTxState[EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE])},   
        {EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE,NULL,NULL,                                     waitAckResultEventActionFinish,&(pstTxState[EN_MAC_TX_STATE_FAILED])}  //failed    
    },

},

/*
*
*/
//EN_MAC_TX_STATE_SUCCED
{
    .handle = EN_MAC_TX_STATE_SUCCED,
    .numTransitions = 1,
    .transitions = (STATEM_TRANSITION_ST[])
    {
        {EN_MAC_TX_EVENT_TYPE_TRANS_FINISH,NULL,NULL,transSuccedEventAction, &(pstTxState[EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE])},
    },
    
},

/*
*
*/
//EN_MAC_TX_STATE_FAILED
{
    .handle = EN_MAC_TX_STATE_FAILED,
    .numTransitions = 1,
    .transitions = (STATEM_TRANSITION_ST[])
    {
        {EN_MAC_TX_EVENT_TYPE_TRANS_FINISH,NULL,NULL,transFailedEventAction, &(pstTxState[EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE])},
    },
}

};


void macTxStateMachineInit(PFUNC_TX_CALLBACK* ppArrayFun)
{
    uint8_t i;
    if(ppArrayFun != NULL)
    {
        for(i=0;i<EN_TRANS_REQ_MAX;i++)
        {
            s_stTxCtrlBlock.ppMacCallbackTx[i] = ppArrayFun[i];           
            s_pTransEventDestId[i] = 0xFF;
        }
    }

    s_dwTransEventBitM = 0x00000000;
    s_dwMacTxEventTypeBitMask = 0x00000000;
    s_stTxCtrlBlock.enHandlingEventType = EN_TRANS_REQ_NONE;
    s_stTxCtrlBlock.pPacketToSend = NULL;
    s_stTxCtrlBlock.stLbtCtrl.byLbtCount = 0;
    s_stTxCtrlBlock.stLbtCtrl.byLbtMaxTimes = 0;
    //s_stTxCtrlBlock.stLbtCtrl.byEventType = EN_TRANS_REQ_NONE;

    s_stTxCtrlBlock.stRegisterCtrl.byCrtlFlag = 0;
    s_stTxCtrlBlock.stRegisterCtrl.byRetryCount = 0;
    s_stTxCtrlBlock.stRegisterCtrl.byRetryMaxTimes = 0;
    s_stTxCtrlBlock.stRegisterCtrl.byEventType = EN_TRANS_REQ_NONE;
    s_stTxCtrlBlock.stRegisterCtrl.bySeq = 1;
    s_stTxCtrlBlock.stRegisterCtrl.stRetryTimer.Handle = 0x00E0;

    s_stTxCtrlBlock.stRetryUpCtrl.byCrtlFlag = 0;
    s_stTxCtrlBlock.stRetryUpCtrl.byRetryCount = 0;
    s_stTxCtrlBlock.stRetryUpCtrl.byRetryMaxTimes = 0;
    s_stTxCtrlBlock.stRetryUpCtrl.byEventType = EN_TRANS_REQ_NONE;
    s_stTxCtrlBlock.stRetryUpCtrl.bySeq = 1;
    s_stTxCtrlBlock.stRetryUpCtrl.stRetryTimer.Handle = 0x00E1;

    //仅HUB有 多并发下行重传控制
    for(i=0;i<DOWNLINK_CONCURRENCY_CAPABILITY;i++)
    {
        s_stTxCtrlBlock.sRetryDownCtrl[i].byCrtlFlag = 0;
        s_stTxCtrlBlock.sRetryDownCtrl[i].byRetryCount = 0;
        s_stTxCtrlBlock.sRetryDownCtrl[i].byRetryMaxTimes = 0;
        s_stTxCtrlBlock.sRetryDownCtrl[i].byEventType = EN_TRANS_REQ_NONE;
        s_stTxCtrlBlock.sRetryDownCtrl[i].bySeq = 1;
        s_stTxCtrlBlock.sRetryDownCtrl[i].stRetryTimer.Handle = 0x00E2 + i;
    }
    
    stateM_init(&s_instTxStateMachine ,&pstTxState[EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE] ,&pstTxState[EN_MAC_TX_STATE_FAILED],&s_stTxCtrlBlock);
}

bool isTxStateRfIdle()
{
    if(s_instTxStateMachine.currentState->handle == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE)
    {
      return true;
    }
    return false;
}

TRANS_REQ_E getMacTxStateHandlingEventType()
{
  if(s_instTxStateMachine.currentState->handle == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE)
  {
    return EN_TRANS_REQ_NONE;
  }
  return s_stTxCtrlBlock.enHandlingEventType;
}
